# Copyright (c) HySoP 2011-2024
#
# This file is part of HySoP software.
# See "https://particle_methods.gricad-pages.univ-grenoble-alpes.fr/hysop-doc/"
# for further info.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import numpy as np
from hysop.tools.htypes import check_instance, first_not_None
from hysop.tools.misc import upper_pow2_or_3
from hysop.backend.device.codegen.base.enum_codegen import EnumCodeGenerator
from hysop.backend.device.codegen.base.struct_codegen import StructCodeGenerator
from hysop.backend.device.opencl.opencl_types import OpenClTypeGen
from hysop.constants import DirectionLabels
[docs]
class SpaceIndices(StructCodeGenerator):
def __init__(
self,
name,
typegen,
var_prefix,
stype,
workdim,
vsize=1,
typedef=True,
comments=None,
):
assert vsize in [1, 2, 3, 4, 8, 16]
stype = stype.replace("fbtype", typegen.fbtype)
name += f"{workdim}D_{stype.capitalize()}{vsize}"
if isinstance(typedef, bool):
if typedef is True:
typedef = name + "_s"
else:
typedef = None
dtype = self.build_dtype(typegen, var_prefix, stype, vsize, workdim)
super().__init__(
name=name, dtype=dtype, typegen=typegen, typedef=typedef, comments=comments
)
self.workdim = workdim
self.vsize = vsize
self.stype = stype
[docs]
@staticmethod
def build_dtype(typegen, var_prefix, stype, vsize, workdim):
tg = typegen
stype1 = tg.dtype_from_str(stype)
stypen = tg.dtype_from_str(f"{stype}{vsize}")
dtype = []
fn = f"{var_prefix}{DirectionLabels[0]}"
field = (fn, stypen)
dtype.append(field)
for i in range(workdim - 2, -1, -1):
fn = f"{var_prefix}{DirectionLabels[workdim-1-i]}"
field = (fn, stype1)
dtype.append(field)
return np.dtype(dtype)
[docs]
def create(self, *args, **kwds):
raise NotImplementedError()
[docs]
class GlobalIndices(SpaceIndices):
def __init__(self, typegen, workdim, **kwds):
super().__init__(
typegen=typegen,
workdim=workdim,
name="GlobalIndices",
var_prefix="I",
stype="int",
**kwds,
)
[docs]
class GlobalCoordinates(SpaceIndices):
def __init__(self, typegen, workdim, **kwds):
super().__init__(
typegen=typegen,
workdim=workdim,
name="GlobalCoordinates",
var_prefix="",
stype="fbtype",
**kwds,
)
[docs]
class GlobalFieldInfo(StructCodeGenerator):
def __init__(self, typegen, workdim, vsize, typedef=True, **kwds):
gi = GlobalIndices(typegen=typegen, workdim=workdim, vsize=vsize)
gc = GlobalCoordinates(typegen=typegen, workdim=workdim, vsize=vsize)
dtype = self.build_dtype(gi, gc)
name = "GlobalFieldInfo{}D_{}{}_{}{}".format(
workdim, gi.stype.capitalize(), vsize, gc.stype.capitalize(), vsize
)
if isinstance(typedef, bool):
if typedef is True:
typedef = name + "_s"
else:
typedef = None
super().__init__(
name=name, dtype=dtype, typedef=typedef, typegen=typegen, **kwds
)
self.require(gi.name, gi)
self.require(gc.name, gc)
self.workdim = workdim
self.vsize = vsize
[docs]
@staticmethod
def build_dtype(gi, gc):
dtype = [("idx", gi.dtype), ("pos", gc.dtype)]
return np.dtype(dtype)
[docs]
class GlobalFieldInfos(StructCodeGenerator):
def __init__(self, field_names, typegen, workdim, vsize, typedef=True, **kwds):
gfi = GlobalFieldInfo(typegen=typegen, workdim=workdim, vsize=vsize)
dtype = []
for fname in field_names:
field = (fname, gfi.dtype)
dtype.append(field)
dtype = np.dtype(dtype)
name = gfi.name.replace("GlobalFieldInfo", "GlobalFieldInfos")
name += "_" + "_".join(field_names)
if isinstance(typedef, bool):
if typedef is True:
typedef = name + "_s"
else:
typedef = None
super().__init__(
name=name, dtype=dtype, typedef=typedef, typegen=typegen, **kwds
)
self.require(gfi.name, gfi)
self.field_names = field_names
self.workdim = workdim
self.vsize = vsize
if __name__ == "__main__":
from hysop.backend.device.codegen.base.opencl_codegen import OpenClCodeGenerator
from hysop.backend.device.codegen.base.test import _test_typegen
tg = _test_typegen("double", float_dump_mode="dec")
idx = GlobalIndices(typegen=tg, workdim=3, vsize=4)
pos = GlobalCoordinates(typegen=tg, workdim=3, vsize=4)
gfi = GlobalFieldInfo(typegen=tg, workdim=3, vsize=2)
gfis = GlobalFieldInfos(typegen=tg, workdim=2, vsize=8, field_names=("P", "V"))
cg = OpenClCodeGenerator("test_generator", tg)
cg.require("idx", idx)
cg.require("pos", pos)
cg.require("gfi", gfi)
cg.require("gfis", gfis)
cg.edit()
cg.test_compile()